package com.rogo.oauth
{
	import com.adobe.crypto.HMAC;
	import com.adobe.crypto.SHA1;
	import com.adobe.utils.Base64;
	
	import flash.net.URLRequest;
	
	/**
	 * OAuth Util
	 * 
	 * @author Rogo
	 */	
	public class OAuthCore
	{
		public function OAuthCore()
		{
		}
		
		//--------------------------------------------------------------------------
		//
		//  Methods
		//
		//--------------------------------------------------------------------------
		
		/**
		 * 获取一个签名的URLRequest
		 * 
		 * oauth_nonce
		 * oauth_timestamp
		 * oauth_consumer_key
		 * oauth_signature_method
		 * oauth_version
		 * oauth_signature
		 * 
		 * 默认生成上面6个参数 使用urlParams添加参数
		 * 
		 * @param method 请求方法
		 * @param url 请求路径
		 * @param urlParams 请求参数
		 * @param oauthKey 请求密钥
		 */		
		public static function getSignatureUrlReq(method:String, 
												  url:String, 
												  urlParams:URLParams, 
												  oauthKey:OAuthKey):URLRequest
		{
			urlParams.addParam(new URLParam('oauth_nonce', getNonce()));
			urlParams.addParam(new URLParam('oauth_timestamp', getTimeStamp()));
			urlParams.addParam(new URLParam('oauth_consumer_key', oauthKey.oauth_consumer_key));
			urlParams.addParam(new URLParam('oauth_signature_method', 'HMAC-SHA1'));
			urlParams.addParam(new URLParam('oauth_version', '1.0'));
			
			var signature:String = getSignature(method, url, urlParams, oauthKey);
			
			urlParams.addParam(new URLParam('oauth_signature', signature));
			
			var urlReq:URLRequest = new URLRequest(url);
			urlReq.method = method;
			urlReq.data = urlParams.toURLVariables();
			
			return urlReq;
		}
		
		/**
		 * 获取一个没有签名的URLRequest
		 * 
		 * @param method 请求方法
		 * @param url 请求路径
		 * @param urlParams 请求参数
		 * @return 
		 */		
		public static function getUrlReq(method:String, 
										 url:String, 
										 urlParams:URLParams):URLRequest
		{
			var urlReq:URLRequest = new URLRequest(url);
			urlReq.method = method;
			urlReq.data = urlParams.toURLVariables();
			
			return urlReq;
		}
		
		/**
		 * 获取签名
		 * 
		 * 所有的OAuth请求使用同样的算法来生成(signature base string)签名字符基串和签名。
		 *  
		 */		
		private static function getSignature(method:String, 
											 url:String, 
											 urlParams:URLParams, 
											 oauthKey:OAuthKey):String
		{
			var basestring:String = getBaseString(method,url, urlParams);
			var key:String = oauthKey.oauth_consumer_secret + '&' + 
				(oauthKey.oauth_token_secret ? oauthKey.oauth_token_secret : '');
			var res:String = Base64.encode(HMAC.hash(key, basestring, SHA1));
			return res;
		}
		
		/**
		 * 获取base string
		 * 
		 * base string是把http方法名,请求URL以及请求参数用&字符连起来后做URL Encode编码。
		 * 具体来讲，base string由http方法名，之后是&，接着是过url编码(url-encoded)之后
		 * 的url和访问路径及&。接下来，把所有的请求参数包括POST方法体中的参数，经过排序(按参数
		 * 名进行文本排序，如果参数名有重复则再安参数值进行重复项目排序)，使用%3D替代=号，并且
		 * 使用%26作为每个参数之间的分隔符，拼接成一个字符串。
		 * 
		 * @param method
		 * @param url
		 * @param params
		 * @return 
		 */		
		private static function getBaseString(method:String, 
											 url:String, 
											 urlParams:URLParams):String
		{
			// 算法伪码:
			//httpMethod + "&" +
			//url_encode(  base_uri ) + "&" +
			//	sorted_query_params.each  { | k, v |
			//		url_encode ( k ) + "%3D" +
			//		url_encode ( v )
			//	}.join("%26")
			
			var baseMethod:String = method.toUpperCase();
			var baseUrl:String = encodeURIComponent(url);
			var baseParams:String = urlParams.toBaseParams();
			var basestring:String = baseMethod + '&' + baseUrl + '&' + baseParams;
			
			return basestring;
		}
		
		/**
		 * 获取nonce
		 * 
		 * @return 
		 */		
		private static function getNonce():String 
		{
			return String(new Date().getTime()).substr(6);
		}
		
		/**
		 * 获取时间戳
		 * 
		 * @return 
		 */		
		private static function getTimeStamp():String 
		{
			var date:Date = new Date();
			return date.time.toString().substr(0, 10);;
		}
		
	}
}